Skip to content

feat(validator): add unique validator constraint#179

Merged
imdhemy merged 24 commits into
koala-ts:2.xfrom
EmanFateen:add-unqiue-compariosn-type
May 22, 2026
Merged

feat(validator): add unique validator constraint#179
imdhemy merged 24 commits into
koala-ts:2.xfrom
EmanFateen:add-unqiue-compariosn-type

Conversation

@EmanFateen
Copy link
Copy Markdown
Contributor

@EmanFateen EmanFateen commented May 15, 2026

Overview

In this PR, I have introduced a new validation constraint called unique.

export type UniqueOptions = ConstraintOptions<{
  message?: string;
  normalizer?: (value: unknown) => unknown;
  fields?: string[];
}>;

It's exposed through the builtInConstraints and can be used like

const rules = {
  tags: [{ unique: {} }],
  emails: [{ unique: { normalizer: value => typeof value === 'string' ? value.trim() : value } }],
  coordinates: [{ unique: { fields: ['latitude', 'longitude'] } }],
  usernames: [{ unique: { groups: ['create'] } }],
};
  • Main purpose of this constraint is to validate whether the given collection contains only unique elements.
  • By default, uniqueness is checked with strict comparison semantics.
  • The constraint supports a normalizer to transform values before uniqueness is checked.
  • The constraint also supports fields to validate uniqueness based on a selected combination of object fields.
  • This constraint preserves the current optional-field behavior, which means if the value is undefined the constraint will return no violations.

Changes made:

  1. Added the unique constraint under comparison constraints.
  2. Covered the required cases in unique.test file.
  3. Exposed the unique constraint through the builtInConstraints object.
Q A
License GPLv3
Issue Closes #170 >

@EmanFateen EmanFateen requested a review from imdhemy as a code owner May 15, 2026 14:51
EmanFateen and others added 11 commits May 18, 2026 15:32
# Conflicts:
#	src/validator/constraints/index.ts
* feat: add passing type constraint

* chore: cover type constraint violation

* chore: support matching type constraint values

* chore: support type constraint alternatives

* chore: allow optional type constraint values

* chore: support type constraint custom message

* chore: format type constraint alternatives

* chore: register type constraint

# Conflicts:
#	src/validator/constraints/index.ts

* chore: fix code style

* chore: use TypeOptions due to rebase

* Simplify type constraint message formatting

* chore: add separate test case for the undefined values.

* chore: refactor getDefaultMessageWith method.

* chore: add a list of AllowedTypes types

* chore: code format

* chore: remove redundant test case

* chore: remove redundant check

* chore: fix AllowedTypes

* chore: inline options

* chore: rename test case

* chore: use one default message

* chore: inline method

* chore: rename AllowedType

* chore: refactor  normalizedTypes

* chore: remove the undefined type case from each

* chore(validator): make constraint options generic

* chore: align type constraint options

* chore: code refactoring

* chore: fix type mismatch

---------

Co-authored-by: Dhemy <imdhemy@gmail.com>
# Conflicts:
#	src/validator/constraints/index.ts
@EmanFateen EmanFateen force-pushed the add-unqiue-compariosn-type branch from 66fbc49 to 0cc1b39 Compare May 18, 2026 12:33
@EmanFateen EmanFateen marked this pull request as draft May 18, 2026 12:55
@EmanFateen EmanFateen marked this pull request as ready for review May 19, 2026 09:14
@imdhemy imdhemy requested a review from Copilot May 22, 2026 17:01
@imdhemy imdhemy changed the title feat(Validation): Add unique validator constraint feat(validator): Add unique validator constraint May 22, 2026
@imdhemy imdhemy changed the title feat(validator): Add unique validator constraint feat(validator): add unique validator constraint May 22, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new built-in unique validation constraint under the validator’s comparison constraints, enabling uniqueness checks for array values (optionally via normalization and/or a field-combination key for arrays of objects).

Changes:

  • Added unique constraint implementation with message, normalizer, and fields options.
  • Added Vitest coverage for core unique behaviors.
  • Registered and exported unique (and UniqueOptions) via the constraints public API.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/validator/constraints/index.ts Registers unique in builtInConstraints and exports it from the constraints module.
src/validator/constraints/comparison/unique.ts Implements the unique constraint with optional normalization and field-based uniqueness checks.
src/validator/constraints/comparison/unique.test.ts Adds tests for uniqueness, custom messages, normalization, and field-combination checks.

Comment thread src/validator/constraints/index.ts Outdated
Comment thread src/validator/constraints/comparison/unique.ts Outdated
Comment thread src/validator/constraints/comparison/unique.ts Outdated
Comment thread src/validator/constraints/comparison/unique.test.ts
Copy link
Copy Markdown
Member

@imdhemy imdhemy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EmanFateen Thank you!

I’ve made some improvements to the tests and adjusted the source code to align with the intended behavior. Here’s a summary of the changes:

  • Changed unique to compare array elements by value, not reference:

    • nested arrays with the same values now fail validation.
    • objects with the same values now fail validation.
    • different array/object values still pass.
  • Fixed normalizer semantics:

    • normalizer now always runs on each array element first.
    • configured fields are read from normalized elements.
    • normalizer no longer runs on individual field values.
  • Added missing value-shape coverage in unique.test.ts:

    • arrays of scalars
    • arrays of arrays
    • arrays of objects
    • object field combinations
  • Added explicit null and undefined behavior:

    • whole-value undefined passes by bypass.
    • whole-value null fails as non-array.
    • [null] and [undefined] pass.
    • [null, null] and [undefined, undefined] fail.
  • Split failure messages by failure reason:

    • non-array values use This value should be an array.
    • duplicate values use This array should contain only unique elements.
  • Aligned wording from collection to array.

  • Regrouped the test suite:

    • non-array values
    • arrays of scalars
    • arrays of arrays
    • arrays of objects
    • options
  • Switched test declarations from it(...) to test(...).

  • Reworded test names to standalone phrases such as:

    • validation passes when ...
    • validation fails when ...
    • validation normalizes ...

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comment thread src/validator/constraints/comparison/unique.ts
Comment thread src/validator/constraints/comparison/unique.ts
Comment thread src/validator/constraints/comparison/unique.ts
Comment thread src/validator/constraints/comparison/unique.test.ts
@imdhemy imdhemy merged commit 6fec725 into koala-ts:2.x May 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[validator] Add built-in unique comparison validator constraint

3 participants